using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SumerCoreDevOps.Application.Dtos.Requests.Auth;
using SumerCoreDevOps.Application.Dtos.Responses.Auth;
using SumerCoreDevOps.Application.Users.Commands;
using SumerCoreDevOps.Application.Users.Queries;
using SumerCoreDevOps.Infrastructure.Identity;
using System.Security.Claims;

namespace SumerCoreDevOps.ControlApi.Controllers;

/// <summary>
/// 用户认证 API
/// 提供登录、登出、刷新Token、获取当前用户信息等功能
/// </summary>
[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly JwtTokenService _jwtService;
    private readonly TokenBlacklistService _tokenBlacklistService;
    private readonly ILogger<AuthController> _logger;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="mediator">MediatR 中介者</param>
    /// <param name="jwtService">JWT Token 服务</param>
    /// <param name="logger">日志记录器</param>
    public AuthController(IMediator mediator, JwtTokenService jwtService, TokenBlacklistService tokenBlacklistService, ILogger<AuthController> logger)
    {
        _mediator = mediator;
        _jwtService = jwtService;
        _tokenBlacklistService = tokenBlacklistService;
        _logger = logger;
    }

    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="request">登录请求（用户名和密码）</param>
    /// <returns>登录成功返回访问Token和刷新Token</returns>
    /// <response code="200">登录成功，返回Token信息</response>
    /// <response code="401">用户名或密码错误</response>
    /// <response code="403">用户已被锁定</response>
    /// <response code="500">服务器内部错误</response>
    [HttpPost("login")]
    [ProducesResponseType(typeof(LoginResponse), 200)]
    public async Task<ActionResult<LoginResponse>> Login([FromBody] LoginRequest request)
    {
        try
        {
            // 验证凭据
            var user = await _mediator.Send(new ValidateCredentialsCommand(
                request.Username,
                request.Password
            ));

            if (user == null)
            {
                _logger.LogWarning("登录失败：用户名或密码错误 - {Username}", request.Username);
                return Unauthorized(new { message = "用户名或密码错误" });
            }

            // 检查用户是否被锁定
            if (user.IsLocked)
            {
                _logger.LogWarning("登录失败：用户已被锁定 - {Username}", request.Username);
                return StatusCode(403, new { message = "用户已被锁定", reason = user.LockReason });
            }

            // 获取用户角色
            var userWithRoles = await _mediator.Send(new GetUserWithRolesQuery(user.Id));
            if (userWithRoles == null)
            {
                _logger.LogError("获取用户角色失败 - 用户不存在: {UserId}", user.Id);
                return StatusCode(500, new { message = "获取用户信息失败" });
            }
            var roles = userWithRoles.Roles.Select(r => r.RoleName).ToList();

            // 获取用户权限
            var permissionEntities = await _mediator.Send(new GetUserPermissionsQuery(user.Id));
            var permissions = permissionEntities.Select(p => p.PermissionCode).ToList();

            // 生成Token
            var accessToken = _jwtService.GenerateAccessToken(user.Id, user.Username, roles, permissions);
            var refreshToken = _jwtService.GenerateRefreshToken();

            // TODO: 将refreshToken保存到数据库（可选，用于refresh token轮换策略）

            var tokenExpiration = _jwtService.GetTokenExpiration();

            _logger.LogInformation("用户登录成功: {Username} (ID: {UserId})", user.Username, user.Id);

            return Ok(new LoginResponse
            {
                AccessToken = accessToken,
                RefreshToken = refreshToken,
                TokenType = "Bearer",
                ExpiresIn = tokenExpiration.AccessTokenExpirationMinutes * 60, // 转换为秒
                User = new UserInfo
                {
                    UserId = user.Id,
                    Username = user.Username,
                    Email = user.Email,
                    DisplayName = user.DisplayName,
                    Roles = roles,
                    Permissions = permissions
                }
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "登录失败: {Username}", request.Username);
            return StatusCode(500, new { message = "登录失败", error = ex.Message });
        }
    }

    /// <summary>
    /// 刷新访问Token
    /// </summary>
    /// <param name="request">刷新Token请求</param>
    /// <returns>新的访问Token和刷新Token</returns>
    /// <response code="200">Token刷新成功</response>
    /// <response code="401">刷新Token无效</response>
    /// <response code="500">服务器内部错误</response>
    [HttpPost("refresh")]
    [ProducesResponseType(typeof(LoginResponse), 200)]
    public async Task<ActionResult<LoginResponse>> RefreshToken([FromBody] RefreshTokenRequest request)
    {
        try
        {
            // 验证旧的访问Token（允许过期，但检查黑名单）
            var userId = await _jwtService.GetUserIdFromTokenAsync(request.AccessToken);
            if (userId == null)
            {
                _logger.LogWarning("刷新Token失败：无效的访问Token");
                return Unauthorized(new { message = "无效的访问Token" });
            }

            // 检查Token是否已被列入黑名单
            if (await _tokenBlacklistService.IsTokenBlacklistedAsync(request.AccessToken))
            {
                _logger.LogWarning("刷新Token失败：Token已被列入黑名单 - UserId: {UserId}", userId);
                return Unauthorized(new { message = "Token已失效" });
            }

            // TODO: 验证refreshToken是否存在于数据库中（可选）

            // 获取用户信息
            var user = await _mediator.Send(new GetUserWithRolesQuery(userId.Value));
            if (user == null)
            {
                _logger.LogWarning("刷新Token失败：用户不存在 - UserId: {UserId}", userId);
                return Unauthorized(new { message = "用户不存在" });
            }

            // 检查用户是否被锁定
            if (user.IsLocked)
            {
                _logger.LogWarning("刷新Token失败：用户已被锁定 - UserId: {UserId}", userId);
                return StatusCode(403, new { message = "用户已被锁定" });
            }

            var roles = user.Roles.Select(r => r.RoleName).ToList();
            var permissionEntities = await _mediator.Send(new GetUserPermissionsQuery(user.Id));
            var permissions = permissionEntities.Select(p => p.PermissionCode).ToList();

            // 生成新Token
            var newAccessToken = _jwtService.GenerateAccessToken(user.Id, user.Username, roles, permissions);
            var newRefreshToken = _jwtService.GenerateRefreshToken();

            // 将旧的访问Token加入黑名单
            await _tokenBlacklistService.BlacklistTokenAsync(request.AccessToken, userId.Value, "Token刷新");
            
            // TODO: 更新数据库中的refreshToken（可选）

            var tokenExpiration = _jwtService.GetTokenExpiration();

            _logger.LogInformation("Token刷新成功: UserId={UserId}", userId);

            return Ok(new LoginResponse
            {
                AccessToken = newAccessToken,
                RefreshToken = newRefreshToken,
                TokenType = "Bearer",
                ExpiresIn = tokenExpiration.AccessTokenExpirationMinutes * 60,
                User = new UserInfo
                {
                    UserId = user.Id,
                    Username = user.Username,
                    Email = user.Email,
                    DisplayName = user.DisplayName,
                    Roles = roles,
                    Permissions = permissions
                }
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "刷新Token失败");
            return StatusCode(500, new { message = "刷新Token失败", error = ex.Message });
        }
    }

    /// <summary>
    /// 用户登出
    /// </summary>
    /// <returns>登出结果</returns>
    /// <response code="200">登出成功</response>
    [HttpPost("logout")]
    [Authorize]
    public async Task<ActionResult> Logout()
    {
        try
        {
            var userId = User.FindFirst("userId")?.Value;
            var username = User.FindFirst("username")?.Value;
            var token = HttpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");

            // 将Token加入黑名单
            if (!string.IsNullOrEmpty(userId) && !string.IsNullOrEmpty(token))
            {
                await _tokenBlacklistService.BlacklistTokenAsync(token, long.Parse(userId), "用户主动登出");
            }
            
            // TODO: 清除数据库中的refreshToken（可选）

            _logger.LogInformation("用户登出: {Username} (ID: {UserId})", username, userId);

            return Ok(new { message = "登出成功" });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "登出失败");
            return StatusCode(500, new { message = "登出失败", error = ex.Message });
        }
    }

    /// <summary>
    /// 获取当前登录用户信息
    /// </summary>
    /// <returns>当前用户详细信息</returns>
    /// <response code="200">成功返回用户信息</response>
    /// <response code="401">未授权，需要登录</response>
    /// <response code="500">服务器内部错误</response>
    [HttpGet("me")]
    [Authorize]
    [ProducesResponseType(typeof(UserInfo), 200)]
    public async Task<ActionResult<UserInfo>> GetCurrentUser()
    {
        try
        {
            var userIdClaim = User.FindFirst("userId")?.Value;
            if (userIdClaim == null || !long.TryParse(userIdClaim, out var userId))
            {
                return Unauthorized(new { message = "无效的Token" });
            }

            // 获取用户详细信息
            var user = await _mediator.Send(new GetUserWithRolesQuery(userId));
            if (user == null)
            {
                return NotFound(new { message = "用户不存在" });
            }

            var roles = user.Roles.Select(r => r.RoleName).ToList();
            var permissionEntities = await _mediator.Send(new GetUserPermissionsQuery(user.Id));
            var permissions = permissionEntities.Select(p => p.PermissionCode).ToList();

            return Ok(new UserInfo
            {
                UserId = user.Id,
                Username = user.Username,
                Email = user.Email,
                DisplayName = user.DisplayName,
                Roles = roles,
                Permissions = permissions
            });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取当前用户信息失败");
            return StatusCode(500, new { message = "获取用户信息失败", error = ex.Message });
        }
    }

    /// <summary>
    /// 修改当前用户密码
    /// </summary>
    /// <param name="request">修改密码请求</param>
    /// <returns>操作结果</returns>
    /// <response code="200">密码修改成功</response>
    /// <response code="400">旧密码错误</response>
    /// <response code="401">未授权，需要登录</response>
    /// <response code="500">服务器内部错误</response>
    [HttpPut("change-password")]
    [Authorize]
    public async Task<ActionResult> ChangeMyPassword([FromBody] ChangeMyPasswordRequest request)
    {
        try
        {
            var userIdClaim = User.FindFirst("userId")?.Value;
            if (userIdClaim == null || !long.TryParse(userIdClaim, out var userId))
            {
                return Unauthorized(new { message = "无效的Token" });
            }

            await _mediator.Send(new ChangePasswordCommand(
                userId,
                request.OldPassword,
                request.NewPassword
            ));

            _logger.LogInformation("用户修改密码成功: UserId={UserId}", userId);

            return Ok(new { message = "密码修改成功，请重新登录" });
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { message = ex.Message });
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "修改密码失败");
            return StatusCode(500, new { message = "修改密码失败", error = ex.Message });
        }
    }
}




